// ColoredCube.js (c) 2012 matsuda
// Vertex shader program
var VSHADER_SOURCE =
  'attribute vec4 a_position;\n' +
  'varying vec4 v_position;\n' +
  'void main() {\n' +
  '  v_position = a_position;\n' +
  '  gl_Position = a_position;\n' +
  '}\n';

// Fragment shader program
var FSHADER_SOURCE =
  'precision mediump float;\n' +
    'uniform samplerCube u_skybox;\n' +
    'uniform mat4 u_viewDirectionProjectionInverse;\n' +
    'varying vec4 v_position;\n' +
  'void main() {\n' +
  '  vec4 t = u_viewDirectionProjectionInverse * v_position;\n' +
  '  gl_FragColor = textureCube(u_skybox, normalize(t.xyz / t.w));\n' +
  '}\n';

var loadCount = 0;

var canvas = document.getElementById('webgl');

var gl = getWebGLContext(canvas);

var texture = gl.createTexture();
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);

var faceInfos = [
    {
        target: gl.TEXTURE_CUBE_MAP_POSITIVE_X,
        url: '../resources/pos-x.jpg'
    },
    {
        target: gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
        url: '../resources/neg-x.jpg'
    },
    {
        target: gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
        url: '../resources/pos-y.jpg'
    },
    {
        target: gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
        url: '../resources/neg-y.jpg'
    },
    {
        target: gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
        url: '../resources/pos-z.jpg'
    },
    {
        target: gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,
        url: '../resources/neg-z.jpg'
    },
];
faceInfos.forEach((faceInfo) => {
    const {target, url} = faceInfo;

    const level = 0;
    const internalFormat = gl.RGBA;
    const width = 512;
    const height = 512;
    const format = gl.RGBA;
    const type = gl.UNSIGNED_BYTE;

    // setup each face so it's immediately renderable
    gl.texImage2D(target, level, internalFormat, width, height, 0, format, type, null);

    // Asynchronously load an image
    const image = new Image();
    image.src = url;
    image.addEventListener('load', function() {
        // Now that the image has loaded make copy it to the texture.
        gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
        gl.texImage2D(target, level, internalFormat, format, type, image);
        // gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
        loadCount ++;
        if(loadCount == 6){
            main();
        }
    });
});

function main() {


  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }
    var program = gl.program;

    var positionLocation = gl.getAttribLocation(program, "a_position");
    var skyboxLocation = gl.getUniformLocation(program, "u_skybox");
    var viewDirectionProjectionInverseLocation = gl.getUniformLocation(program, "u_viewDirectionProjectionInverse");
    var positionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

    var positions = new Float32Array(
        [
            -1, -1,
            1, -1,
            -1,  1,
            -1,  1,
            1, -1,
            1,  1,
        ]);
    gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);

    var size = 2;          // 2 components per iteration
    var type = gl.FLOAT;   // the data is 32bit floats
    var normalize = false; // don't normalize the data
    var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
    var offset = 0;        // start at the beginning of the buffer
    gl.vertexAttribPointer(positionLocation, size, type, normalize, stride, offset);
    gl.enableVertexAttribArray(positionLocation);



    // gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
    // gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);

    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.enable(gl.CULL_FACE);
    gl.enable(gl.DEPTH_TEST);

    var projectionMatrix = new Matrix4().setPerspective(30, 1, 1, 2000);
    var cameraMatrix = new Matrix4().setLookAt(0.55, 0.55, 0.55, 0, 0, 0, 0, 1, 0);
    var viewMatrix = cameraMatrix.invert();
    var viewDirectionProjectionMatrix = projectionMatrix.multiply(viewMatrix);
    var viewDirectionProjectionInverseMatrix = viewDirectionProjectionMatrix.invert();

  gl.uniformMatrix4fv(viewDirectionProjectionInverseLocation, false, viewDirectionProjectionInverseMatrix.elements);


  // Clear color and depth buffer
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  // Draw the cube
    gl.uniform1i(skyboxLocation, 1);
    gl.drawArrays(gl.TRIANGLES, 0, 1 * 6);

}
